import { ClientId, type Position } from '../types/vtuber';
import config from '../config/index';

function throttle(func: Function, delay: number = 100): Function {
  let lastTime = 0;
  return function (...args: any[]) {
    const currentTime = Date.now();
    if (currentTime - lastTime >= delay) {
      lastTime = currentTime;
      return func.apply(this, args);
    }
  };
}

function debounce(func: Function, delay: number): Function {
  let timeoutId: ReturnType<typeof setTimeout>;

  return function (...args: any[]) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}
function sleep(time: number = 1000): Promise<void> {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
}

function errorReport(error: { name: string; message: string; stack: string }): void {
  if (!window?.ClientMonitor?.reportFrameErrors) {
    return;
  }
  window.ClientMonitor.reportFrameErrors(
    {
      category: 'js',
      grade: 'Error'
    },
    {
      name: error.name,
      message: error.message,
      stack: error.stack
    }
  );
}

function getDomain(url?: string): string {
  try {
    const hostname = url ? new URL(url).hostname : location.hostname;
    let _domain = '';
    const arr = hostname.split('.');
    const ipReg = /^[0-9]+$/;
    if (arr[0] === 'localhost' || ipReg.test(arr[0])) {
      _domain = '10jqka.com.cn';
      return _domain;
    } else {
      arr.length > 2 ? (_domain = arr.slice(1).join('.')) : (_domain = arr.join('.'));
      return _domain;
    }
  } catch (error) {
    errorReport({
      name: `获取域名的方法错误 ${error.name}`,
      message: error.message,
      stack: error.stack
    });
  }
}

function buildQueryString(params?: { [key: string]: string }): string {
  if (!params) {
    return '';
  }
  const queryString = Object.keys(params)
    .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&');
  return queryString;
}

function setPosition(position: Position, dom: HTMLElement) {
  Object.keys(position).forEach((key: keyof Position) => {
    if (position[key]) {
      dom.style[key] = position[key];
    }
  });
}

function sendStat(suffix: string) {
  window.TA && window.TA.log({ id: config.statId + suffix });
}

// 检查浏览器是否是 Chrome 49
function judgeChrome49(): boolean {
  const chromeVersion = /Chrome\/([0-9.]+)/.exec(navigator.userAgent);
  if (chromeVersion) {
    const versionNumber = parseInt(chromeVersion[1].split('.')[0]);
    return versionNumber === 49;
  }
  return false;
}

function getFile(key: string) {
  return new Promise((resolve) => {
    window.API.use({
      method: 'external.getUserPath',
      success: function (userPath) {
        const thsExammarketPath = `${userPath}vtuber${key}.log`;
        window.API.use({
          method: 'fileReader.open',
          data: thsExammarketPath,
          success: function (d) {
            if (!d) {
              resolve('');
              return;
            }
            window.API.use({
              method: 'fileReader.read',
              success: function (str) {
                resolve(str);
                window.API.use({ method: 'fileReader.close' });
              }
            });
          }
        });
      },
      notClient: () => {
        resolve(window.localStorage.getItem(key));
      }
    });
  }).catch((error) => {
    errorReport({
      name: `使用客户端协议获取文件信息错误 ${error.name}`,
      message: error.message,
      stack: error.stack
    });
  });
}

function setFile(key: string, value: string) {
  try {
    window.API.use({
      method: 'external.getUserPath',
      success: function (userPath) {
        const thsExammarketPath = `${userPath}vtuber${key}.log`;
        window.API.use({
          method: 'fileWriter.open',
          data: thsExammarketPath,
          success: function () {
            window.API.use({
              method: 'fileWriter.write',
              data: value,
              success: function () {
                window.API.use({ method: 'fileWriter.close' });
              }
            });
          }
        });
      },
      notClient: () => {
        window.localStorage.setItem(key, value);
      }
    });
  } catch (error) {
    errorReport({
      name: `使用客户端协议写入文件信息错误 ${error.name}`,
      message: error.message,
      stack: error.stack
    });
  }
}


function toggleAutoPlay(userid: string) {
  const {
    localstorageKeys: { autoPlayKey }
  } = config;
  const autoPlayKeyUserid = `${autoPlayKey}${userid}`;
  getFile(autoPlayKeyUserid).then((autoplayStatus) => {
    const autoplayFlag = autoplayStatus ? '' : '1';
    setFile(autoPlayKeyUserid, autoplayFlag);
  });
}

function getClientId(): Promise<ClientId | void> {
  return new Promise((resolve) => {
    window.API.use({
      method: 'Util.getHxProduct',
      success: function (num: ClientId) {
        resolve(num);
      },
      notClient: () => {
        resolve(ClientId.jrds);
      }
    });
  });
}
function getCookieValue(name: string): string | null {
  const cookies = document.cookie.split(';');
  for (const cookie of cookies) {
    const [key, value] = cookie.split('=');
    if (key.trim() === name) {
      return value ? value.trim() : null;
    }
  }
  return null;
}

function getUserId(): Promise<string | void> {
  return new Promise((resolve) => {
    window.API.use({
      method: 'Passport.get',
      data: 'userid',
      success: function (num: number) {
        resolve(num + '');
      },
      notClient: () => {
        resolve(getCookieValue('userid') + '');
      }
    });
  });
}
// 判断gpu加速是否正常开启
function isGPUAccelerated(): boolean {
  // todo 临时用来判断gpu加速是否正常，上线前删除
  if (window.notGpu) {
    return false;
  }
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  const extension = (gl as WebGLRenderingContext)?.getExtension?.('WEBGL_debug_renderer_info');
  const info = (gl as WebGLRenderingContext)?.getParameter?.(extension?.UNMASKED_RENDERER_WEBGL);
  const result = info?.toLowerCase?.()?.includes?.('swiftshader');
  // 手动释放 WebGL 上下文对象
  (gl as WebGLRenderingContext)?.getExtension?.('WEBGL_lose_context')?.loseContext?.();
  // 移除 Canvas 元素
  canvas.remove();
  return !result;
}

// 当前版本是否支持，9.30.39.0000之前的版本存在严重的gpu加速异常关闭的bug
const isSupportVersion = (basicVersion: number = 930390000): Promise<boolean> =>
  new Promise((resolve) => {
    // todo 临时用来判断客户端版本，上线前删除
    if (window.notVersion) {
      resolve(false);
    }
    window.API.use({
      method: 'Util.getHxVer',
      success: function (result: string) {
        resolve(+result.slice(3).replace(/\./g, '') >= basicVersion);
      },
      error: function () {
        // 上报
        resolve(false);
      },
      notClient: function () {
        resolve(true);
      }
    });
  });

class StutterDetector {
  private frameRates: number[];
  private fluctuationFrameRates: number[];
  private fluctuations: number[];
  private currentTime: number;
  constructor() {
    // 记录最近三次的帧率
    this.frameRates = [];
    // 记录波动发生的时间
    this.fluctuations = [];
    // 记录最近六次帧率
    this.fluctuationFrameRates = [];
    // 记录波动次数
    this.currentTime = 0;
  }
  // 30s内检测3次帧率都小于24帧或者帧率小于10
  checkFrameRate(currentFrameRate: number) {
    // todo 临时用来模拟不流畅，上线前删除
    if (window.notSmooth) {
      return false;
    }
    // 每次调用时更新帧率列表，确保只保存最近的三次帧率
    if (this.frameRates.length >= 3) {
      this.frameRates.shift();
    }
    this.frameRates.push(currentFrameRate);
    // 判断帧率列表是否连续三次都低于24fps
    return this.frameRates.every((item) => item >= 24) || currentFrameRate < 10;
  }
  // 1分钟内波动次数超过5次
  checkFluctuation(currentFrameRate: number) {
    // todo 临时用来模拟不流畅，上线前删除
    if (window.notSmooth) {
      return false;
    }
    // 更新当前时间（假设每次调用时间间隔为10秒）
    this.currentTime += 10;

    // 清除一分钟前的波动记录
    while (this.fluctuations.length > 0 && this.fluctuations[0] <= this.currentTime - 60) {
      this.fluctuations.shift();
    }

    // 记录当前帧率，并计算波动次数
    if (this.fluctuationFrameRates.length > 0) {
      const lastFrameRate = this.fluctuationFrameRates[this.fluctuationFrameRates.length - 1];
      if (Math.abs(currentFrameRate - lastFrameRate) > 20) {
        this.fluctuations.push(this.currentTime);
      }
    }

    // 保存当前帧率
    if (this.fluctuationFrameRates.length >= 6) {
      this.fluctuationFrameRates.shift();
    }
    this.fluctuationFrameRates.push(currentFrameRate);
    // 检查波动次数是否超过5次
    return this.fluctuations.length < 5;
  }
}

// 导出
export {
  throttle,
  debounce,
  sleep,
  errorReport,
  getDomain,
  buildQueryString,
  setPosition,
  sendStat,
  judgeChrome49,
  getFile,
  setFile,
  toggleAutoPlay,
  getClientId,
  getUserId,
  isGPUAccelerated,
  isSupportVersion,
  StutterDetector
};
